package com.changyinBus.common.utils;

import com.alibaba.fastjson2.JSON;
import com.csrcbank.apibank.api.exception.EncryptTypeException;
import com.csrcbank.apibank.api.exception.NullArgsException;
import com.csrcbank.apibank.api.utils.AESUtils;
import com.csrcbank.apibank.api.utils.Constant;
import com.csrcbank.apibank.api.utils.SM4Util;
import com.csrcbank.apibank.api.utils.SignUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/**
 * API接入demo
 */
public class ApiUtil {

    /**
     * 加密 返回加密数据 加密类型支持SM4和AES
     *
     * @param encryptType 加密类型
     * @param secretKey   私钥
     * @param dataText      待加密字符串
     * @return 返回加密字符串
     * @throws Exception
     */
    public static String encryptBySecretKey(String encryptType, String secretKey,String dataText) throws Exception {

        //请求参数判空
        if (encryptType==null ||encryptType.length()==0
                || secretKey==null ||secretKey.length()==0
                || dataText==null ||dataText.length()==0 ) {
            throw new NullArgsException("参数不能为空");
        }

        String encryptData = "";
        if (Constant.SM4.equalsIgnoreCase(encryptType)) {
            encryptData = SM4Util.encryptToBase64Str(dataText, secretKey);
        } else if (Constant.AES.equalsIgnoreCase(encryptType)) {
                encryptData = AESUtils.encrypt(dataText, secretKey);
        } else {
            throw new EncryptTypeException("加密类型不正确");
        }
        return encryptData;
    }

    /**
     * 解密 返回解密数据 解密类型支持SM4和AES
     *
     * @param decryptType 解密类型
     * @param secretKey   私钥
     * @param encryptText 加密字符串
     * @return 返回解密字符串
     * @throws Exception
     */
    public static String decryptBySecretKey(String decryptType, String secretKey, String encryptText) throws Exception {

        //请求参数判空
        if (decryptType==null ||decryptType.length()==0
                || secretKey==null ||secretKey.length()==0
                || encryptText==null ||encryptText.length()==0 ){
            throw new NullArgsException("参数不能为空");
        }

        String decryptData = "";
        if (Constant.SM4.equalsIgnoreCase(decryptType)) {
            decryptData = SM4Util.decryptToBase64Str(encryptText, secretKey);
        } else if (Constant.AES.equalsIgnoreCase(decryptType)) {
            decryptData = AESUtils.decrypt(encryptText, secretKey);
        } else {
            throw new EncryptTypeException("解密类型不正确");
        }
        return decryptData;
    }

    /**
     * 加签 通过证书私钥加签 返回加签字符串
     *
     * @param certPath     证书路径
     * @param certFileName 证书名称
     * @param password     证书密码
     * @param algorithm    算法
     * @param encryptText  加密字符串
     * @return
     * @throws Exception
     */
    public static String signByCertPrivateKey(String certPath, String certFileName, String password, String algorithm, String encryptText) throws Exception {
        if (certPath==null ||certPath.length()==0
                || certFileName==null ||certFileName.length()==0
                || password==null ||password.length()==0
                || algorithm==null ||algorithm.length()==0){
            throw new NullArgsException("参数不能为空");
        }

        return SignUtils.sign(encryptText, certPath, certFileName, password, algorithm);

    }

    /**
     * 验签 通过证书公钥验签 返回验签是否成功
     *
     * @param certPath     证书路径
     * @param certFileName 证书名称
     * @param algorithm    算法
     * @param signText     签名字符串
     * @param dataText     解密的明文字符串
     * @return 返回验签是否成功
     * @throws Exception
     */
    public static Boolean verifyByCertPublicKey(
            String certPath, String certFileName, String algorithm, String signText, String dataText) throws Exception {
        if (certPath == null || certPath.length() == 0
                || certFileName == null || certFileName.length() == 0
                || signText == null || signText.length() == 0
                || algorithm == null || algorithm.length() == 0
                || dataText == null || dataText.length() == 0) {
            throw new NullArgsException("参数不能为空");
        }

        return SignUtils.verify(signText, dataText, certPath, certFileName, algorithm);
    }

    /**
     * 发送post请求 并获取返回值
     *
     * @param url          请求URL
     * @param bodyParams   请求体参数集合
     * @param connectTimeout  单位毫秒
     * @param readTimeout  单位毫秒
     * @return 返回响应数据
     */
    public static String sendPost(String url, Map<String, String> bodyParams,int connectTimeout,int readTimeout) throws Exception {
        OutputStreamWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        HttpURLConnection conn =  null;
        try {
            URL realUrl = new URL(url);
            conn = (HttpURLConnection) realUrl.openConnection();
            // 设置请求方式为POST
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            //设置是否向HttpURLConnection输出
            conn.setDoOutput(true);
            //设置是否从HttpURLConnection读入
            conn.setDoInput(true);
            //设置连接超时时间
            conn.setConnectTimeout(connectTimeout);
            //设置读取超时时间
            conn.setReadTimeout(readTimeout);
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "application/json");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");

            //连接服务器
            conn.connect();

            // 获取URLConnection对象对应的输出流
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            // 设置请求体
            if (bodyParams != null) {
                //将map类型参数转为json字符串
                String body = JSON.toJSONString(bodyParams);

                System.out.println("request===============>" + body);
                out.write(body);
            }
            // flush输出流的缓冲
            out.flush();

            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            throw e;
        }finally {
            if(out!=null){
                out.close();
            }
            if(in!=null){
                in.close();
            }
            if(conn != null){
                conn.disconnect();
            }
        }
        return result.toString();
    }

}
